

package cn.shengchao.examstart.user.acl.adapters.repositories;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.shengchao.base.enums.DisEnableStatusEnum;
import cn.shengchao.base.utils.SecureUtils;
import cn.shengchao.examstart.user.acl.adapters.message.MemberStudent;
import cn.shengchao.examstart.user.acl.ports.repositories.IUserRepository;
import cn.shengchao.examstart.user.domain.entity.*;
import cn.shengchao.examstart.user.infrastructure.dao.*;
import cn.shengchao.examstart.user.infrastructure.dao.po.*;
import cn.shengchao.examstart.user.ohs.local.messages.SaveUserPreference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import top.continew.starter.core.exception.BaseException;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Repository
public class UserRepository implements IUserRepository {

    @Autowired
    private UserDao userDao;

    @Autowired
    private UserPreferenceDao userPreferenceDao;

    @Autowired
    private UserRealPersonDao userRealPersonDao;

    @Autowired
    private UserRoleDao userRoleDao;

    @Autowired
    private UserSocialDao userSocialDao;

    @Override
    public Optional<User> getUserBySocial(String appid, String openId, String unionId) {
        TUserSocial tUserSocial = userSocialDao.selectOne(new LambdaQueryWrapper<TUserSocial>()
                .eq(TUserSocial::getOpenId, openId)
                .eq(TUserSocial::getAppId, appid));
        if (tUserSocial == null) {
            return Optional.empty();
        }
        if (tUserSocial.getUnionId() == null && unionId != null) {
            tUserSocial.setUnionId(unionId);
            userSocialDao.updateById(tUserSocial);
        }
        User user = new User();
        if (tUserSocial.getUserId() == null) {
            user.setUserSocial(Lists.newArrayList(of(tUserSocial)));
            return Optional.of(user);
        }
        TUser tUser = userDao.selectById(tUserSocial.getUserId());
        user.setId(tUser.getId());
        user.setName(tUser.getNickname());
        user.setUserSocial(Lists.newArrayList(of(tUserSocial)));
        user.setPhone(tUser.getPhone());
        user.setAvatar(tUser.getAvatar());
        List<TUserRole> tUserRoles = userRoleDao.selectList(new LambdaQueryWrapper<TUserRole>()
                .eq(TUserRole::getUserId, tUserSocial.getUserId()));
        if (tUserRoles != null) {
            user.setRoleId(tUserRoles.stream().map(TUserRole::getRoleId).toList());
        } else {
            user.setRoleId(new ArrayList<>());
        }
        return Optional.of(user);
    }

    private static UserSocial of(TUserSocial tUserSocial) {
        UserSocial userSocial = new UserSocial();
        userSocial.setAppId(tUserSocial.getAppId());
        userSocial.setOpenId(tUserSocial.getOpenId());
        userSocial.setSource(tUserSocial.getSource());
        userSocial.setUnionId(tUserSocial.getUnionId());
        userSocial.setMetaJson(tUserSocial.getMetaJson());
        userSocial.setLastLoginTime(tUserSocial.getLastLoginTime());
        return userSocial;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public User saveWxUser(User user) {
        TUser tUser = new TUser();
        //保存用户信息
        TUserRole userRole;
        if (!StrUtil.isEmpty(user.getPhone())) {
            tUser = userDao.selectOne(new LambdaQueryWrapper<TUser>().eq(TUser::getPhone, SecureUtils
                    .encryptFieldByAes(user.getPhone())));
            if (tUser == null) {
                tUser = new TUser();
                tUser.setDeptId(-1L);
                tUser.setPassword(user.getPassword());
                tUser.setUsername(user.getUsername());
                tUser.setNickname(user.getName());
                tUser.setCreateTime(LocalDateTime.now());
            }
            if (user.getId() != null) {
                tUser.setId(user.getId());
                if (!user.getName().contains("***")) {
                    tUser.setNickname(user.getName());
                }
            }
            tUser.setPhone(user.getPhone());
            tUser.setAvatar(user.getAvatar());
            userDao.insertOrUpdate(tUser);
            if (user.getId() == null) {
                userRole = userRoleDao.selectOne(new LambdaQueryWrapper<TUserRole>()
                        .eq(TUserRole::getUserId, tUser.getId())
                        .eq(TUserRole::getRoleId, -1));
                if (userRole == null) {
                    userRole = new TUserRole();
                    userRole.setRoleId(-1L);
                    userRole.setUserId(tUser.getId());
                    userRoleDao.insert(userRole);
                }
            }
            user.setId(tUser.getId());
        }
        //保存社交账户信息
        TUser finalTUser = tUser;
        user.getUserSocial().forEach(userSocial -> {
            TUserSocial tUserSocial = userSocialDao.selectOne(new LambdaQueryWrapper<TUserSocial>()
                    .eq(TUserSocial::getAppId, userSocial.getAppId())
                    .eq(TUserSocial::getOpenId, userSocial.getOpenId())
                    .eq(TUserSocial::getSource, userSocial.getSource()));
            //更新
            if (tUserSocial != null) {
                tUserSocial.setUserId(finalTUser.getId());
                tUserSocial.setMetaJson(userSocial.getMetaJson());
                tUserSocial.setUnionId(userSocial.getUnionId());
                tUserSocial.setLastLoginTime(userSocial.getLastLoginTime());
                userSocialDao.updateById(tUserSocial);
            } else {
                //新增
                tUserSocial = new TUserSocial();
                tUserSocial.setUserId(finalTUser.getId());
                tUserSocial.setAppId(userSocial.getAppId());
                tUserSocial.setOpenId(userSocial.getOpenId());
                tUserSocial.setSource(userSocial.getSource());
                tUserSocial.setUnionId(userSocial.getUnionId());
                tUserSocial.setMetaJson(userSocial.getMetaJson());
                userSocialDao.insert(tUserSocial);
            }
        });
        List<TUserRole> userRoles = userRoleDao.selectList(new LambdaQueryWrapper<TUserRole>()
                .eq(TUserRole::getUserId, tUser.getId()));
        if (userRoles == null) {
            userRoles = new ArrayList<>();
        }
        user.setRoleId(userRoles.stream().map(TUserRole::getRoleId).toList());
        return user;
    }

    @Transactional
    @Override
    public PlatformUser savePlatformUser(PlatformUser user) {
        TUser tUser = userDao.selectOne(new LambdaQueryWrapper<TUser>().eq(TUser::getPhone, SecureUtils
                .encryptFieldByAes(user.getPhone())));
        //保存用户信息
        if (tUser == null) {
            tUser = new TUser();
            tUser.setStatus(DisEnableStatusEnum.ENABLE);
            tUser.setDeptId(-1L);
            tUser.setPassword(user.getPassword());
            tUser.setUsername(user.getUsername());
            tUser.setPhone(user.getPhone());
            tUser.setNickname(user.getNickname());
            tUser.setAvatar(user.getAvatar());
            tUser.setCreateTime(LocalDateTime.now());
            userDao.insert(tUser);
            tUser.setPhone(user.getPhone());
            if (user.getId() == null) {
                TUserRole userRole = userRoleDao.selectOne(new LambdaQueryWrapper<TUserRole>()
                        .eq(TUserRole::getUserId, tUser.getId())
                        .eq(TUserRole::getRoleId, -1));
                if (userRole == null) {
                    userRole = new TUserRole();
                    userRole.setRoleId(-1L);
                    userRole.setUserId(tUser.getId());
                    userRoleDao.insert(userRole);
                }
            }
            user.setId(tUser.getId());
        } else {
            throw new BaseException("手机号已存在");
        }
        return user;
    }

    @Override
    public User ofUnionId(String unionId) {
        TUserSocial tUserSocial = userSocialDao.selectOne(Wrappers.lambdaQuery(TUserSocial.class).eq(TUserSocial::getUnionId, unionId).orderByDesc(TUserSocial::getCreateTime).last("limit 1"));
        return tUserSocial==null?null:of(tUserSocial.getUserId());
    }

    @Override
    public User of(Long id) {
        TUser tUser = userDao.selectById(id);
        return of(tUser);
    }

    @Override
    public UserPreference getUserPreference(Long id) {
        TUserPreference userPreferenceList = userPreferenceDao.selectOne(new LambdaQueryWrapper<TUserPreference>()
                .eq(TUserPreference::getUserId, id));
        UserPreference userPreference = new UserPreference();
        if (userPreferenceList != null) {
            userPreference.setName(userPreferenceList.getName());
            userPreference.setValue(userPreferenceList.getValue());
        }
        return userPreference;
    }

    private User of(TUser tUser) {
        User user = new User();
        user.setId(tUser.getId());
        user.setAvatar(tUser.getAvatar());
        user.setName(tUser.getNickname());
        user.setPhone(tUser.getPhone());
        user.setCreateTime(tUser.getCreateTime());
        user.setUsername(tUser.getUsername());
        List<TUserSocial> tUserSocial = userSocialDao.selectList(new LambdaQueryWrapper<TUserSocial>()
                .eq(TUserSocial::getUserId, tUser.getId()));
        user.setUserSocial(tUserSocial.stream().map(UserRepository::of).toList());
        return user;
    }

    @Override
    public void saveUserPreference(SaveUserPreference userPreferences, Long userId) {
        userPreferenceDao.delete(new LambdaQueryWrapper<TUserPreference>().eq(TUserPreference::getUserId, userId));
        TUserPreference tUserPreference = new TUserPreference();
        tUserPreference.setUserId(userId);
        tUserPreference.setName(userPreferences.getName());
        tUserPreference.setValue(userPreferences.getValue());
        userPreferenceDao.insert(tUserPreference);
    }

    @Override
    public void saveRealPerson(UserRealPerson realPerson) {
        TUserRealPerson tUserRealPerson = new TUserRealPerson();
        tUserRealPerson.setUserId(realPerson.getUserId());
        tUserRealPerson.setRealName(realPerson.getRealName());
        tUserRealPerson.setIdcard(realPerson.getIdcard());
        tUserRealPerson.setIdcardFront(realPerson.getIdcardFront());
        tUserRealPerson.setIdcardBack(realPerson.getIdcardBack());
        tUserRealPerson.setApiResult(realPerson.getApiResult());
        tUserRealPerson.setTime(realPerson.getTime());
        userRealPersonDao.insert(tUserRealPerson);
    }

    @Override
    public UserRealPerson getRealPerson(Long uid) {
        TUserRealPerson tUserRealPerson = userRealPersonDao.selectOne(new LambdaQueryWrapper<TUserRealPerson>()
                .eq(TUserRealPerson::getUserId, uid));
        UserRealPerson userRealPerson = new UserRealPerson();
        if (tUserRealPerson != null) {
            userRealPerson.setIdcard(tUserRealPerson.getIdcard());
            userRealPerson.setRealName(tUserRealPerson.getRealName());
            userRealPerson.setIdcardFront(tUserRealPerson.getIdcardFront());
            userRealPerson.setIdcardBack(tUserRealPerson.getIdcardBack());
            userRealPerson.setApiResult(tUserRealPerson.getApiResult());
            userRealPerson.setTime(tUserRealPerson.getTime());
            return userRealPerson;
        }
        return new UserRealPerson();
    }

    @Override
    public List<User> selectByPhone(String phone) {
        List<TUser> tUsers = userDao.selectList(new LambdaQueryWrapper<TUser>().eq(TUser::getPhone, SecureUtils.encryptFieldByAes(phone)));
        if (CollUtil.isEmpty(tUsers)) {
            return List.of();
        } else {
            List<User> users = new ArrayList<>();
            for (TUser tUser : tUsers) {
                User user = new User();
                user.setId(tUser.getId());
                user.setAvatar(tUser.getAvatar());
                user.setName(tUser.getNickname());
                user.setPhone(tUser.getPhone());
                user.setUsername(tUser.getUsername());
                users.add(user);
            }
            return users;
        }
    }

    @Override
    public List<User> getUserList(List<Long> list) {
        if (list.isEmpty()) {
            return List.of();
        }
        List<TUser> tUsers = userDao.selectList(new LambdaQueryWrapper<TUser>().in(TUser::getId, list));
        return tUsers.stream().map(tUser -> {
            User user = new User();
            user.setId(tUser.getId());
            user.setAvatar(tUser.getAvatar());
            user.setName(tUser.getNickname());
            user.setPhone(tUser.getPhone());
            user.setUsername(tUser.getUsername());
            user.setCreateTime(tUser.getCreateTime());
            return user;
        }).toList();
    }

    @Override
    public void updateUserDept(Long userId, Long deptId) {
        TUser tUser = userDao.selectById(userId);
        if (tUser != null) {
            tUser.setDeptId(deptId);
            userDao.updateById(tUser);
        }
    }

    @Override
    public List<MemberStudent> selectMemberStudent(Long userId, String searchValue) {
        return userDao.selectMemberStudent(userId, searchValue);
    }
}
